package com.maruping.disk.file.service.io;

import com.maruping.disk.file.service.FileIoService;
import com.maruping.disk.file.service.FileService;
import com.maruping.disk.mybatis.ztree.ZtreeEntity;
import com.obs.services.ObsClient;
import com.obs.services.exception.ObsException;
import com.obs.services.model.*;
import com.maruping.disk.mybatis.entity.PtFileEntity;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Service
public class FileIoServiceImpl implements FileIoService {
    @Value("${end.point}")
    private String endpoint="";
    @Value("${ak}")
    private String  ak = "";
    @Value("${sk}")
    private String  sk = "";
    @Value("${bucket.name}")
    private String  bucketName = "";


    // 新增getter方法，供外部获取存储桶名称
    public String getBucketName() {
        return bucketName;
    }

    private ObsClient obsClient = null;
    @Resource
    private FileService fileService;


    public ObsClient getObsClient(){
        if(this.obsClient == null){
            this.obsClient = new ObsClient(ak,sk,endpoint);
        }
        return this.obsClient;
    }
    private Logger logger = LogManager.getLogger(this.getClass());



    @Override
    public void syncFileData() {
        ObjectListing list = getObsClient().listObjects(bucketName);
        List<ObsObject> listObjects = list.getObjects();
        PtFileEntity ptFileEntity = null;
        List<PtFileEntity> ptFileEntityList = new ArrayList<>();

        List<PtFileEntity> ptFileEntityList1 = fileService.queryFileListAll();
        String uuid = "";

        for(ObsObject obsObject:listObjects){

            ptFileEntity = new PtFileEntity();
            ptFileEntityList.add(ptFileEntity);
            ptFileEntity.setParentUuid("-1");
            ptFileEntity.setFilePath(obsObject.getObjectKey());
            uuid = UUID.randomUUID().toString();
            for (PtFileEntity ptFileEntityItem:ptFileEntityList1){
                if (obsObject.getObjectKey().equals(ptFileEntityItem.getFilePath())){
                    uuid = ptFileEntityItem.getFileUuid();
                    break;
                }
            }
            ptFileEntity.setFileUuid(uuid);
            ptFileEntity.setFileCapacity(obsObject.getMetadata().getContentLength());
//            logger.info("obsClient obsKey:" + obsObject.getObjectKey()
//                    + "  obsClient obsSize:"  + obsObject.getMetadata().getContentLength() +
//                    "  obsClient isFolder:" +isFolder(obsObject.getObjectKey()));
            /**
             * 判断是否为文件夹
             */
            if(isFolder(obsObject.getObjectKey())){
                ptFileEntity.setFileType(FILE_TYPE_FOLDER);
            }else{
                ptFileEntity.setFileType(FILE_TYPE_FILE);
            }
            /**
             * 获取文件名称
             */
            ptFileEntity.setFileName(getFileName(obsObject.getObjectKey()));

//            logger.info(ptFileEntity);

        }

        for(PtFileEntity child:ptFileEntityList){
            for(PtFileEntity parent:ptFileEntityList){
                //同一文件
                if(child.getFilePath().equals(parent.getFilePath())){
                    continue;
                }
                //如果父亲是文件跳过
                if(FILE_TYPE_FILE == parent.getFileType()){
                    continue;
                }

                //文件路径包含父亲节点路径
                if(child.getFilePath().indexOf(parent.getFilePath()) != - 1){
                    child.setParentUuid(parent.getFileUuid());
                }
            }
        }

        logger.info(ptFileEntityList);
        fileService.saveFileInfo(ptFileEntityList);

    }

    @Override
    public void mkdirFileInfo(String parentId, String folderName) {
        PtFileEntity entity = fileService.queryFileInfoById(parentId);
        String fileName = folderName;
        if (entity != null){
            fileName = entity.getFilePath() + FILE_SEPARATOR + folderName;
        }
        fileName = fileName + FILE_SEPARATOR;
        getObsClient().putObject(bucketName, fileName, new ByteArrayInputStream(new byte[0]));
        syncFileData();
    }

    @Override
    public void uploadFile(String parentId, String fileName, InputStream inputStream) {
        PtFileEntity entity = fileService.queryFileInfoById(parentId);
        String fileNameU = fileName;
        if (entity != null){
            fileNameU = entity.getFilePath() + fileName;
        }

        getObsClient().putObject(bucketName, fileNameU, inputStream);
        syncFileData();
    }

    @Override
    public String getShareUrl(String fileUuid) {
        PtFileEntity entity = fileService.queryFileInfoById(fileUuid);
        TemporarySignatureRequest request = new TemporarySignatureRequest();
        request.setBucketName(bucketName);
        request.setObjectKey(entity.getFilePath());
        request.setRequestDate(new Date());
        request.setExpires(60*60);
        TemporarySignatureResponse signature = getObsClient().createTemporarySignature(request);
        String url = signature.getSignedUrl();
        return url;
    }

    // 新增：查询文件ACL权限（关联Ztree）
    @Override
    public List<ZtreeEntity> queryFileAcl(String fileUuid) {
        // 1. 查询ACL权限树（前端展示的权限选项）
        List<ZtreeEntity> ztreeList = fileService.queryAclZtree();
        if (ztreeList == null || ztreeList.isEmpty()) {
            return ztreeList;
        }

        // 2. 查询文件信息
        PtFileEntity ptFileEntity = fileService.queryParentFileById(fileUuid);
        if (ptFileEntity == null) {
            logger.warn("文件不存在：fileUuid={}", fileUuid);
            return ztreeList;
        }

        ObsClient obsClient = null;
        try {
            // 3. 获取OBS文件当前ACL
            obsClient = getObsClient();
            AccessControlList acl = obsClient.getObjectAcl(bucketName, ptFileEntity.getFilePath());

            // 4. 匹配权限并设置勾选状态
            for (ZtreeEntity ztree : ztreeList) {
                for (GrantAndPermission grant : acl.getGrantAndPermissions()) {
                    if (ztree.getId().equals(grant.getPermission().toString())) {
                        ztree.setChecked(true);
                        break;
                    }
                }
            }
        } catch (ObsException e) {
            logger.error("查询文件ACL失败：fileUuid={}, error={}", fileUuid, e.getErrorMessage());
        } finally {
            if (obsClient != null) {
                try {
                    obsClient.close();
                } catch (Exception e) {
                    logger.error("关闭ObsClient失败", e);
                }
            }
        }
        return ztreeList;
    }

    // 新增：设置文件ACL权限
    @Override
    public void setFileAcl(String fileUuid, String aclArray) {
        // 1. 查询文件信息
        PtFileEntity ptFileEntity = fileService.queryParentFileById(fileUuid);
        if (ptFileEntity == null) {
            throw new RuntimeException("文件不存在：fileUuid=" + fileUuid);
        }

        ObsClient obsClient = null;
        try {
            // 2. 初始化客户端并获取桶所有者
            obsClient = getObsClient();
            AccessControlList bucketAcl = obsClient.getBucketAcl(bucketName);
            Owner owner = bucketAcl.getOwner();

            // 3. 构建新ACL对象
            AccessControlList newAcl = new AccessControlList();
            newAcl.setOwner(owner);
            newAcl.grantPermission(new CanonicalGrantee(owner.getId()), Permission.PERMISSION_FULL_CONTROL);

            // 4. 解析并授予权限
            String[] permissions = aclArray.split(",");
            for (String perm : permissions) {
                Permission permission = parsePermission(perm);
                newAcl.grantPermission(GroupGrantee.ALL_USERS, permission);
            }

            // 5. 应用ACL设置
            obsClient.setObjectAcl(bucketName, ptFileEntity.getFilePath(), newAcl);
            logger.info("文件ACL设置成功：fileUuid={}, permissions={}", fileUuid, aclArray);
        } catch (ObsException e) {
            logger.error("设置文件ACL失败：fileUuid={}, error={}", fileUuid, e.getErrorMessage());
            throw new RuntimeException("设置权限失败：" + e.getErrorMessage());
        } finally {
            if (obsClient != null) {
                try {
                    obsClient.close();
                } catch (Exception e) {
                    logger.error("关闭ObsClient失败", e);
                }
            }
        }
    }

    // 辅助方法：解析权限字符串为枚举
    private Permission parsePermission(String perm) {
        switch (perm.trim().toUpperCase()) {
            case "READ":
                return Permission.PERMISSION_READ;
            case "WRITE":
                return Permission.PERMISSION_WRITE;
            case "READ_ACP":
                return Permission.PERMISSION_READ_ACP;
            case "WRITE_ACP":
                return Permission.PERMISSION_WRITE_ACP;
            default:
                throw new IllegalArgumentException("不支持的权限类型：" + perm);
        }
    }


   /* @Override
    public void uploadFile(String parentId, String fileName, InputStream inputStream) {
        PtFileEntity entity = fileService.queryFileInfoById(parentId);
        String fileNameU = fileName;
        if (entity != null){
            fileNameU = entity.getFilePath() + fileName;
        }

        getObsClient().putObject(bucketName, fileNameU, inputStream);
        syncFileData();
    }*/

    @Override
    public void copyFile(String parentId, String srcUuidList) {

        PtFileEntity entity = fileService.queryFileInfoById(parentId);
        String floder = "";
        if (entity != null){
            floder = entity.getFilePath() ;
        }
        String[] fileUuidArray = srcUuidList.split(",");
        String filePath= "";
        InputStream inputStream;
        ObsObject obsObject;
                for(String fileUuid:fileUuidArray){
                    entity = fileService.queryFileInfoById(fileUuid);
                    if(entity != null){
                        filePath = floder + entity.getFileName();
                        /*
                        * 判断是否文件夹
                        * */
                        if (FILE_TYPE_FOLDER.equals(entity.getFileType())){
                            getObsClient().putObject(bucketName, filePath, new ByteArrayInputStream(new byte[0]));

                        }else{
                            obsObject = getObsClient().getObject(bucketName,entity.getFilePath());
                            inputStream = obsObject.getObjectContent();
                            getObsClient().putObject(bucketName, filePath, inputStream);
                        }
                    }
                }
        syncFileData();
    }

    @Override
    public ResponseEntity<byte[]> downFile(String fileUuid) {
        PtFileEntity entity = fileService.queryFileInfoById(fileUuid);
        HttpHeaders headers =
                new HttpHeaders();
        headers.setContentDispositionFormData("attachment",
                entity.getFileName());//告知浏览器以下载方式打开
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);//设置MIME类型
        Object obsObject = getObsClient().getObject(bucketName, entity.getFilePath());
        Object inputStream = ((ObsObject) obsObject).getObjectContent();
        byte[] block = new byte[1024];
        int length =0;

        byte[] fileByte=new byte[0];
        try(
                ByteArrayOutputStream byteArrayOutputStream= new ByteArrayOutputStream();
                ){
            while((length= ((InputStream) inputStream).read(block))>0){
                byteArrayOutputStream.write(block,0 ,length);
                byteArrayOutputStream.flush();
            }
            fileByte =byteArrayOutputStream.toByteArray();
        }catch(IOException e){
             logger.info(e);
        }

        return new ResponseEntity<byte[]>(
                fileByte,
                headers,
                HttpStatus.CREATED);
    }

    /**
     * 是否为文件夹
     * @param filePath
     * @return
     */
    private boolean isFolder(String filePath){
        boolean rstB  = false;
        if(filePath.length() > 0){
            String lastStr = filePath.substring(filePath.length() - 1);
            if(FILE_SEPARATOR.equals(lastStr)){
                return true;
            }
        }
        return  rstB;
    }

    /**
     * 获取文件名称
     * @param filePath
     * @return
     */
    private String getFileName(String filePath){
        String fileName = filePath;
        if(filePath.indexOf(FILE_SEPARATOR) != -1){
            String[] fileArray = filePath.split("/");
            if(isFolder(filePath)){
                fileName = fileArray[fileArray.length -1] + FILE_SEPARATOR;
            }else{
                fileName = fileArray[fileArray.length -1];
            }
        }

        return fileName;
    }


}
